home *** CD-ROM | disk | FTP | other *** search
/ Atari Forever 4 / Atari Forever 4.zip / Atari Forever 4.iso / PD_THEMA / EDITOREN / 7UP_PD / DRAGDROP.C < prev    next >
C/C++ Source or Header  |  1998-03-14  |  13KB  |  563 lines

  1. /*
  2.  * Drag & drop sample code.
  3.  * Copyright 1992 Atari Corporation
  4.  *
  5.  * global variables used:
  6.  * gl_apid: our AES application id
  7.  *
  8.  * BUGS/CAVEATS:
  9.  * This code is not re-entrant (it uses a static
  10.  * variable for the pipe name and for saving the
  11.  * SIGPIPE signal handler).
  12.  *
  13.  * While doing the drag and drop, the SIGPIPE
  14.  * signal (write on an empty pipe) is ignored
  15.  */
  16.  
  17. #include <portab.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <tos.h>
  22. #include <aes.h>
  23. #include "dragdrop.h"
  24.  
  25. #ifndef EACCDN
  26. #define EACCDN -36
  27. #endif
  28.  
  29. #ifndef SIGPIPE
  30. #define SIGPIPE 13
  31. #endif
  32.  
  33. #ifndef SIG_IGN
  34. #define SIG_IGN 1L
  35. #endif
  36.  
  37. #ifndef WF_OWNER
  38. #define WF_OWNER 20
  39. #endif
  40.  
  41. #ifndef FA_HIDDEN
  42. #define FA_HIDDEN 0x2
  43. #endif
  44.  
  45. extern int gl_apid;
  46.  
  47. static char pipename[] = "U:\\PIPE\\DRAGDROP.AA";
  48. static long oldpipesig;
  49.  
  50. #ifdef DEBUGGING
  51. #define debug_alert(x, y) form_alert(x, y)
  52. #else
  53. #define debug_alert(x, y)
  54. #endif
  55.  
  56. /* Code for originator */
  57.  
  58. /*
  59.  * create a pipe for doing the drag & drop,
  60.  * and send an AES message to the receipient
  61.  * application telling it about the drag & drop
  62.  * operation.
  63.  *
  64.  * Input Parameters:
  65.  * apid:          AES id of the window owner
  66.  * winid:         target window (0 for background)
  67.  * msx, msy:     mouse X and Y position
  68.  *                  (or -1, -1 if a fake drag & drop)
  69.  * kstate:        shift key state at time of event
  70.  *
  71.  * Output Parameters:
  72.  * exts:          A 32 byte buffer into which the
  73.  *                  receipient's 8 favorite
  74.  *                  extensions will be copied.
  75.  *
  76.  * Returns:
  77.  * A positive file descriptor (of the opened
  78.  * drag & drop pipe) on success.
  79.  * -1 if the receipient doesn't respond or
  80.  *     returns DD_NAK
  81.  * -2 if appl_write fails
  82.  */
  83.  
  84. /*
  85. int
  86. ddcreate(apid, winid, msx, msy, kstate, exts)
  87.           int apid, winid, msx, msy, kstate;
  88.           char exts[];
  89. {
  90.           int fd, i;
  91.           int msg[8];
  92.           long fd_mask;
  93.           char c;
  94.  
  95.           pipename[17] = pipename[18] = 'A';
  96.           fd = -1;
  97.           do {
  98.                      pipename[18]++;
  99.                      if (pipename[18] > 'Z') {
  100.                                 pipename[17]++;
  101.                                 if (pipename[17] > 'Z')
  102.                                           break;
  103.                      }
  104. /* FA_HIDDEN means "get EOF if nobody has pipe open for reading" */
  105.                      fd = Fcreate(pipename, FA_HIDDEN);
  106.           } while (fd == EACCDN);
  107.  
  108.           if (fd < 0) {
  109.                      debug_alert(1, "[1][Fcreate error][OK]");
  110.                      return fd;
  111.           }
  112.  
  113. /* construct and send the AES message */
  114.           msg[0] = AP_DRAGDROP;
  115.           msg[1] = gl_apid;
  116.           msg[2] = 0;
  117.           msg[3] = winid;
  118.           msg[4] = msx;
  119.           msg[5] = msy;
  120.           msg[6] = kstate;
  121.           msg[7] = (pipename[17] << 8) | pipename[18];
  122.           i = appl_write(apid, 16, msg);
  123.           if (i == 0) {
  124.                      debug_alert(1, "[1][appl_write error][OK]");
  125.                      Fclose(fd);
  126.                      return -2;
  127.           }
  128.  
  129. /* now wait for a response */
  130.           fd_mask = 1L << fd;
  131.           i = Fselect(DD_TIMEOUT, &fd_mask, 0L, 0L);
  132.           if (!i || !fd_mask) {    /* timeout happened */
  133.                      debug_alert(1, "[1][ddcreate: Fselect timeout][OK]");
  134. abort_dd:
  135.                      Fclose(fd);
  136.                      return -1;
  137.           }
  138.  
  139. /* read the 1 byte response */
  140.           i = Fread(fd, 1L, &c);
  141.           if (i != 1 || c != DD_OK) {
  142.                      if (i != 1)
  143.                                 debug_alert(1, "[1][ddcreate: read error][OK]");
  144.                      else
  145.                                 debug_alert(1, "[1][ddcreate: DD_NAK][OK]");
  146.                      goto abort_dd;
  147.           }
  148.  
  149. /* now read the "preferred extensions" */
  150.           i = Fread(fd, DD_EXTSIZE, exts);
  151.           if (i != DD_EXTSIZE) {
  152.                      debug_alert(1, "[1][Error reading extensions][OK]");
  153.                      goto abort_dd;
  154.           }
  155.  
  156.           oldpipesig = Psignal(SIGPIPE, SIG_IGN);
  157.           return fd;
  158. }
  159. */
  160.  
  161. /*
  162.  * see if the receipient is willing to accept a certain
  163.  * type of data (as indicated by "ext")
  164.  *
  165.  * Input parameters:
  166.  * fd              file descriptor returned from ddcreate()
  167.  * ext             pointer to the 4 byte file type
  168.  * name            pointer to the name of the data
  169.  * size            number of bytes of data that will be sent
  170.  *
  171.  * Output parameters: none
  172.  *
  173.  * Returns:
  174.  * DD_OK          if the receiver will accept the data
  175.  * DD_EXT         if the receiver doesn't like the data type
  176.  * DD_LEN         if the receiver doesn't like the data size
  177.  * DD_NAK         if the receiver aborts
  178.  */
  179.  
  180. /*
  181. int
  182. ddstry(fd, ext, name, size)
  183.           int fd;
  184.           char *ext, *name;
  185.           long size;
  186. {
  187.           Word hdrlen, i;
  188.           char c;
  189.  
  190. /* 4 bytes for extension, 4 bytes for size, 1 byte for
  191.  * trailing 0
  192.  */
  193.           hdrlen = 9 + strlen(name);
  194.           i = Fwrite(fd, 2L, &hdrlen);
  195.  
  196. /* now send the header */
  197.           if (i != 2) return DD_NAK;
  198.           i = Fwrite(fd, 4L, ext);
  199.           i += Fwrite(fd, 4L, &size);
  200.           i += Fwrite(fd, (long)strlen(name)+1, name);
  201.           if (i != hdrlen) return DD_NAK;
  202.  
  203. /* wait for a reply */
  204.           i = Fread(fd, 1L, &c);
  205.           if (i != 1) return DD_NAK;
  206.           return c;
  207. }
  208. */
  209.  
  210. /* Code for either receipient or originator */
  211.  
  212. /*
  213.  * close a drag & drop operation
  214.  */
  215.  
  216. void
  217. ddclose(fd)
  218.           int fd;
  219. {
  220.           (void)Psignal(SIGPIPE, oldpipesig);
  221.           (void)Fclose(fd);
  222. }
  223.  
  224.  
  225. /* Code for receipient */
  226.  
  227. /*
  228.  * open a drag & drop pipe
  229.  *
  230.  * Input Parameters:
  231.  * ddnam:         the pipe's name (from the last word of
  232.  *                  the AES message)
  233.  * preferext:    a list of DD_NUMEXTS 4 byte extensions we understand
  234.  *                  these should be listed in order of preference
  235.  *                  if we like fewer than DD_NUMEXTS extensions, the
  236.  *                  list should be padded with 0s
  237.  *
  238.  * Output Parameters: none
  239.  *
  240.  * Returns:
  241.  * A (positive) file handle for the drag & drop pipe, on success
  242.  * -1 if the drag & drop is aborted
  243.  * A negative error number if an error occurs while opening the
  244.  * pipe.
  245.  */
  246.  
  247.  
  248. int
  249. ddopen(ddnam,preferext)
  250.           int ddnam;
  251.           char *preferext;
  252. {
  253.           int fd;
  254.           char outbuf[DD_EXTSIZE+1];
  255.  
  256.           pipename[18] = ddnam & 0x00ff;
  257.           pipename[17] = (ddnam & 0xff00) >> 8;
  258.  
  259.           fd = Fopen(pipename, 2);
  260.           if (fd < 0) return fd;
  261.  
  262.           outbuf[0] = DD_OK;
  263.           strncpy(outbuf+1, preferext, DD_EXTSIZE);
  264.  
  265.           oldpipesig = Psignal(SIGPIPE, SIG_IGN);
  266.  
  267.           if (Fwrite(fd, (long)DD_EXTSIZE+1, outbuf) != DD_EXTSIZE+1) {
  268.                      ddclose(fd);
  269.                      return -1;
  270.           }
  271.  
  272.           return fd;
  273. }
  274.  
  275.  
  276. /*
  277.  * ddrtry: get the next header from the drag & drop originator
  278.  *
  279.  * Input Parameters:
  280.  * fd:             the pipe handle returned from ddopen()
  281.  *
  282.  * Output Parameters:
  283.  * name:          a pointer to the name of the drag & drop item
  284.  *                  (note: this area must be at least DD_NAMEMAX bytes long)
  285.  * whichext:     a pointer to the 4 byte extension
  286.  * size:          a pointer to the size of the data
  287.  *
  288.  * Returns:
  289.  * 0 on success
  290.  * -1 if the originator aborts the transfer
  291.  *
  292.  * Note: it is the caller's responsibility to actually
  293.  * send the DD_OK byte to start the transfer, or to
  294.  * send a DD_NAK, DD_EXT, or DD_LEN reply with ddreply().
  295.  */
  296.  
  297. int
  298. ddrtry(fd, name, whichext, size)
  299.           int fd;
  300.           char *name;
  301.           long *size;
  302.           char *whichext;
  303. {
  304.           Word hdrlen;
  305.           int i;
  306.           char buf[80];
  307.  
  308.           i = Fread(fd, 2L, &hdrlen);
  309.           if (i != 2) {
  310.                      return -1;
  311.           }
  312.           if (hdrlen < 9) {         /* this should never happen */
  313.                      return -1;
  314.           }
  315.           i = Fread(fd, 4L, whichext);
  316.           if (i != 4) {
  317.                      return -1;
  318.           }
  319.           whichext[4] = 0;
  320.           i = Fread(fd, 4L, size);
  321.           if (i != 4) {
  322.                      return -1;
  323.           }
  324.           hdrlen -= 8;
  325.           if (hdrlen > DD_NAMEMAX)
  326.                      i = DD_NAMEMAX;
  327.           else
  328.                      i = hdrlen;
  329.           if (Fread(fd, (long)i, name) != i) {
  330.                      return -1;
  331.           }
  332.           hdrlen -= i;
  333.  
  334. /* skip any extra header */
  335.           while (hdrlen > 80) {
  336.                      Fread(fd, 80L, buf);
  337.                      hdrlen -= 80;
  338.           }
  339.           if (hdrlen > 0)
  340.                      Fread(fd, (long)hdrlen, buf);
  341.  
  342.           return 0;
  343. }
  344.  
  345.  
  346. /*
  347.  * send a 1 byte reply to the drag & drop originator
  348.  *
  349.  * Input Parameters:
  350.  * fd:             file handle returned from ddopen()
  351.  * ack:            byte to send (e.g. DD_OK)
  352.  *
  353.  * Output Parameters:
  354.  * none
  355.  *
  356.  * Returns: 0 on success, -1 on failure
  357.  * in the latter case the file descriptor is closed
  358.  */
  359.  
  360.  
  361. int
  362. ddreply(fd, ack)
  363.           int fd, ack;
  364. {
  365.           char c = ack;
  366.  
  367.           if (Fwrite(fd, 1L, &c) != 1L) {
  368.                      Fclose(fd);
  369.           }
  370.           return 0;
  371. }
  372.  
  373. #if 1
  374. /******************************************************************
  375.  *        Here are some sample functions that use the                    *
  376.  *        drag & drop functions above to implement the protocol.     *
  377.  *        These are not complete, working functions yet, but are     *
  378.  *        intended to serve as a "skeleton" for the actual             *
  379.  *        functions that would appear in a drag & drop application. *
  380.  *                                                                                     *
  381.  *        The following global variables are defined:                    *
  382.  *        gl_ourexts: the drag & drop data types we understand        *
  383.  ******************************************************************/
  384.  
  385. /* modify this as necessary */
  386. char gl_ourexts[DD_EXTSIZE] = "ARGS.RTF.TXT";
  387.  
  388. /*
  389.  * rec_ddmsg: given a drag & drop message, act as
  390.  * a receipient and get the data
  391.  *
  392.  * Input Parameters:
  393.  * msg:            Pointer to the 16 byte AES message
  394.  *                  returned by evnt_multi or evnt_mesag
  395.  *
  396.  * calls the following functions to actually perform the paste
  397.  * operation:
  398.  *
  399.  * parseargs(char cmdlin[]):
  400.  *        Given a null terminated string of arguments, separated
  401.  *        by spaces, parse it and perform whatever actions are
  402.  *        appropriate on the arguments (usually file and folder
  403.  *        names)
  404.  *
  405.  * paste_rtf(int win, int fd, long size):
  406.  *        Read "size" bytes from the open file descriptor "fd",
  407.  *        and paste it into the window whose handle is "win".
  408.  *        The data is assumed to be in RTF format.
  409.  *
  410.  * paste_txt(int win, int fd, long size):
  411.  *        Read "size" bytes from the open file descriptor "fd",
  412.  *        and paste it into the window whose handle is "win".
  413.  *        The data is assumed to be ASCII text.
  414.  */
  415.  
  416. void rec_ddmsg(int msg[], char *pathname)
  417. {
  418.           int winid;
  419.           int msx, msy, kstate;
  420.           int fd, pnam;
  421.           int i;
  422.           char txtname[DD_NAMEMAX], ext[5];
  423.           char *cmdline;
  424.           long size;
  425.  
  426.           winid = msg[3];
  427.           msx = msg[4];
  428.           msy = msg[5];
  429.           kstate = msg[6];
  430.           pnam = msg[7];
  431. /*********************************************/
  432. /*
  433.           if(getenv("UNIXMODE")!=NULL)
  434.              pipename[2]=pipename[7]='/';
  435.           else
  436. */
  437.              pipename[2]=pipename[7]='\\';
  438. /*********************************************/
  439.           fd = ddopen(pnam, gl_ourexts);
  440.           if (fd < 0) return;
  441.  
  442.           for(;;) {
  443.                      i = ddrtry(fd, txtname, ext, &size);
  444.                      if (i < 0) {
  445.                                 ddclose(fd);
  446.                                 return;
  447.                      }
  448.                      if (!strncmp(ext, "ARGS", 4)) {
  449.                                 cmdline = malloc((size_t)size+1);
  450.                                 if (!cmdline) {
  451.                                           ddreply(fd, DD_LEN);
  452.                                           continue;
  453.                                 }
  454.                                 ddreply(fd, DD_OK);
  455.                                 Fread(fd, size, cmdline);
  456.                                 ddclose(fd);
  457.                                 cmdline[size] = 0;
  458.                                 strcpy(pathname,cmdline);
  459.                                 free(cmdline);
  460.                                 return;
  461.                      }
  462.                      else if (!strncmp(ext, ".RTF", 4)) {
  463.                                 ddreply(fd, DD_OK);
  464. /*
  465.                                 paste_rtf(winid, fd, size);
  466. */
  467.                                 ddclose(fd);
  468.                                 return;
  469.                      }
  470.                      else if (!strncmp(ext, ".TXT", 4)) {
  471.                                 ddreply(fd, DD_OK);
  472. /*
  473.                                 paste_txt(winid, fd, size);
  474. */
  475.                                 ddclose(fd);
  476.                                 return;
  477.                      }
  478.                      ddreply(fd, DD_EXT);
  479. #ifdef DEBUGGING
  480.                      { char foo[40];
  481.                      strcpy(foo, "[1][rec_ddmsg: unknown extension: |");
  482.                      strcat(foo, ext);
  483.                      strcat(foo, "][OK]");
  484.                      debug_alert(1, foo);
  485.                      }
  486. #endif /* DEBUGGING */
  487.           }
  488. }
  489.  
  490. /*
  491.  * send_ddmsg: construct and send a drag & drop message;
  492.  * we only can send the 1 type of data (specified
  493.  * by ext)
  494.  *
  495.  * Input Parameters:
  496.  * msx, msy:     coordinates where data was dropped
  497.  * kstate:        keyboard state at time of drop
  498.  * name:          name of the data
  499.  * ext:            data type (4 byte extension)
  500.  * size:          size of data
  501.  * data:          pointer to data
  502.  *
  503.  * Output Parameters: none
  504.  *
  505.  * Returns:
  506.  * 0 on success
  507.  * 1 if no window was found
  508.  * 2 if the window belongs to us
  509.  * 3 if the receipient didn't accept the data
  510.  * or a negative error code from the functions
  511.  * above
  512.  */
  513. /*
  514. int
  515. send_ddmsg(msx, msy, kstate, name, ext, size, data)
  516.           int msx, msy, kstate;
  517.           char *name, *ext;
  518.           long size;
  519.           char *data;
  520. {
  521.           int fd;
  522.           int apid, winid;
  523.           int dummy, i;
  524.           char recexts[DD_EXTSIZE];
  525.           extern int gl_apid;
  526.  
  527.           winid = wind_find(msx, msy);
  528.           if (!winid) {
  529.                      debug_alert(1, "[1][Window not found][OK]");
  530.                      return 1;
  531.           }
  532.           if (!_wind_get(winid, WF_OWNER, &apid, &dummy, &dummy, &dummy)) {
  533.                      debug_alert(1, "[1][Owner not found][OK]");
  534.                      return 2;
  535.           }
  536.  
  537.           if (apid == gl_apid) {
  538.                      debug_alert(1, "[1][Same owner][OK]");
  539.                      return 1;         /* huh? that shouldn't happen */
  540.           }
  541.  
  542.           fd = ddcreate(apid, winid, msx, msy, kstate, recexts);
  543.           if (fd < 0) {
  544.                      debug_alert(1, "[1][Couldn't open pipe][OK]");
  545.                      return fd;
  546.           }
  547.           if ((i = ddstry(fd, ext, name, size)) != DD_OK) {
  548.                      if (i == DD_EXT) {
  549.                                 debug_alert(1, "[1][Bad extension][OK]");
  550.                      } else {
  551.                                 debug_alert(1, "[1][Receiver canceled][OK]");
  552.                      }
  553.                      ddclose(fd);
  554.                      return 3;
  555.           }
  556.           Fwrite(fd, size, data);
  557.           ddclose(fd);
  558.           return 0;
  559. }
  560. */
  561. #endif /* 0 */
  562.  
  563.